package com.lbs.jiepiaisi.utils;

import android.graphics.Bitmap;
import android.content.Context;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.os.Environment;
import android.util.Log;
import android.view.View;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
 * Created by yu on 2020-05-25 11:10.
 * Description:
 */
public class BitmapUtils {
    /**
     * 从指定的路径获取Bitmap
     *
     * @param imgPath
     * @return
     */
    public static Bitmap getBitmap(String imgPath) {
        // Get bitmap through image path
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = false;
        newOpts.inPurgeable = true;
        newOpts.inInputShareable = true;
        // Do not compress
        newOpts.inSampleSize = 1;
        newOpts.inPreferredConfig = Config.RGB_565;
        return BitmapFactory.decodeFile(imgPath, newOpts);
    }

    /**
     * 保存Bitmap到指定的路径中 jpeg格式
     *
     * @param bitmap
     * @param outPath
     * @throws FileNotFoundException
     */
    public static boolean storeImage(Bitmap bitmap, String outPath) {
        try {
            FileOutputStream os = new FileOutputStream(outPath);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 60, os);
            os.flush();
            os.close();
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 保存Bitmap到指定的路径中 jpeg格式
     *
     * @param bitmap
     * @param outPath
     * @throws FileNotFoundException
     */
    public static boolean storeCompressImage(Bitmap bitmap, String outPath) {
        try {
            FileOutputStream os = new FileOutputStream(outPath);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
            os.flush();
            os.close();
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 按像素压缩图像，修改图像的宽度/高度
     *
     * @param imgPath
     *            image path
     * @param pixelW
     *            target pixel of width
     * @param pixelH
     *            target pixel of height
     * @return
     */
    public static Bitmap ratio(String imgPath, float pixelW, float pixelH) {
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        // 开始读入图片，此时把options.inJustDecodeBounds 设回true，即只读边不读内容
        newOpts.inJustDecodeBounds = true;
        newOpts.inPreferredConfig = Config.RGB_565;
        // Get bitmap info, but notice that bitmap is null now
        //noinspection UnusedAssignment
        Bitmap bitmap = BitmapFactory.decodeFile(imgPath, newOpts);

        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        // 想要缩放的目标尺寸
        float hh = pixelH;// 设置高度为240f时，可以明显看到图片缩小了
        float ww = pixelW;// 设置宽度为120f，可以明显看到图片缩小了
        // 缩放比。由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
        int be = 1;// be=1表示不缩放
        if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
            be = (int) (newOpts.outWidth / ww);
        } else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放
            be = (int) (newOpts.outHeight / hh);
        }
        if (be <= 0)
            be = 1;
        newOpts.inSampleSize = be;// 设置缩放比例
        // 开始压缩图片，注意此时已经把options.inJustDecodeBounds 设回false了
        bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
        // 压缩好比例大小后再进行质量压缩
        // return compress(bitmap, maxSize); // 这里再进行质量压缩的意义不大，反而耗资源，删除
        return bitmap;
    }


    /**
     * 按大小压缩图像，修改图片的宽高
     *
     * @param image
     * @param pixelW
     *            target pixel of width
     * @param pixelH
     *            target pixel of height
     * @return
     */
    public static Bitmap ratio(Bitmap image, float pixelW, float pixelH) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, os);
        if (os.toByteArray().length / 1024 > 1024) {// 判断如果图片大于1M,进行压缩避免在生成图片（BitmapFactory.decodeStream）时溢出
            os.reset();// 重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, 50, os);// 这里压缩50%，把压缩后的数据存放到baos中
        }
        ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        // 开始读入图片，此时把options.inJustDecodeBounds 设回true了
        newOpts.inJustDecodeBounds = true;
        newOpts.inPreferredConfig = Config.RGB_565;
        Bitmap bitmap = BitmapFactory.decodeStream(is, null, newOpts);
        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        float hh = pixelH;// 设置高度为240f时，可以明显看到图片缩小了
        float ww = pixelW;// 设置宽度为120f，可以明显看到图片缩小了
        // 缩放比。由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
        int be = 1;// be=1表示不缩放
        if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
            be = (int) (newOpts.outWidth / ww);
        } else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放
            be = (int) (newOpts.outHeight / hh);
        }
        if (be <= 0)
            be = 1;
        newOpts.inSampleSize = be;// 设置缩放比例
        // 重新读入图片，注意此时已经把options.inJustDecodeBounds 设回false了
        is = new ByteArrayInputStream(os.toByteArray());
        bitmap = BitmapFactory.decodeStream(is, null, newOpts);
        // 压缩好比例大小后再进行质量压缩
        // return compress(bitmap, maxSize); // 这里再进行质量压缩的意义不大，反而耗资源，删除
        return bitmap;
    }

    /**
     * 按照质量压缩图片，并保存到指定路径
     *
     * @param image
     * @param outPath
     * @param maxSize
     *            target will be compressed to be smaller than this size.(kb)
     * @throws IOException
     */
    public static void compressAndGenImage(Bitmap image, String outPath, int maxSize) throws IOException {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        // scale
        int options = 100;
        // Store the bitmap into output stream(no compress)
        image.compress(Bitmap.CompressFormat.JPEG, options, os);
        // Compress by loop
        while (os.toByteArray().length / 1024 > maxSize) {
            // 重置baos即让下一次的写入覆盖之前的内容
            os.reset();
            // 压缩质量每次减少10
            options -= 8;
            // 将压缩后的图片保存到baos中
            image.compress(Bitmap.CompressFormat.JPEG, options, os);
        }

        // Generate compressed image file
        FileOutputStream fos = new FileOutputStream(outPath);
        fos.write(os.toByteArray());
        fos.flush();
        fos.close();
    }


    /**
     * 按质量压缩图片，并删除原路径图片
     *
     * @param imgPath
     * @param outPath
     * @param maxSize
     *            target will be compressed to be smaller than this size.(kb)
     * @param needsDelete
     *            Whether delete original file after compress
     * @throws IOException
     */
    public static void compressAndGenImage(String imgPath, String outPath, int maxSize, boolean needsDelete)
            throws IOException {
        compressAndGenImage(getBitmap(imgPath), outPath, maxSize);

        // Delete original file
        if (needsDelete) {
            File file = new File(imgPath);
            if (file.exists()) {
                file.delete();
            }
        }
    }

    /**
     * 按大小压缩图像，修改图片的宽高，并保存到指定路径
     *
     * @param image
     * @param outPath
     * @param pixelW
     *            target pixel of width
     * @param pixelH
     *            target pixel of height
     */
    public static void ratioAndGenThumb(Bitmap image, String outPath, float pixelW, float pixelH) {
        Bitmap bitmap = ratio(image, pixelW, pixelH);
        storeImage(bitmap, outPath);
    }

    /**
     * 按大小压缩图像，修改图片的宽高，并保存到指定路径，并删除原图
     *
     * @param outPath
     * @param pixelW
     *            target pixel of width
     * @param pixelH
     *            target pixel of height
     * @param needsDelete
     *            Whether delete original file after compress
     */
    public static void ratioAndGenThumb(String imgPath, String outPath, float pixelW, float pixelH, boolean needsDelete) {
        Bitmap bitmap = ratio(imgPath, pixelW, pixelH);
        storeImage(bitmap, outPath);

        // Delete original file
        if (needsDelete) {
            File file = new File(imgPath);
            if (file.exists()) {
                file.delete();
            }
        }
    }

    /**
     *
     *
     * 根据图片路径，得到压缩过的位图
     *
     * @param path
     * @param width
     * @param height
     * @return returnBitmap
     */
    public static Bitmap getPressedBitmap(String path, int width, int height) {
        // BitmapFactory.Options options = new BitmapFactory.Options();
        // options.inJustDecodeBounds = true;
        //// Bitmap bitmap = BitmapFactory.decodeFile(path, options);
        // options.inSampleSize = getBitmapSampleSize(options, width, height);//
        // getBitmapSampleSize(options,
        // // width,
        // // height)
        // options.inJustDecodeBounds = false;
        // Bitmap returnBitmap = BitmapFactory.decodeFile(path, options);
        // return returnBitmap;
        return ratio(path, width, height);
    }

    /*
     * * 根据要去的宽高，压缩图片
     *
     * @param options options
     *
     * @param reqWidth reqWidth
     *
     * @param reqHeight reqHeight
     *
     * @return inSimpleSize
     */
    public static int getBitmapSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        int imgWidth = options.outWidth;
        int imgHeight = options.outHeight;
        int inSimpleSize = 1;
        if (imgWidth > imgHeight || imgWidth < imgHeight) {
            final int heightRatio = imgWidth / reqWidth;
            final int widthRatio = imgHeight / reqHeight;
            inSimpleSize = widthRatio < heightRatio ? widthRatio : heightRatio;
        }
        return inSimpleSize;
    }

    public static Bitmap matrixBitmap(Bitmap bitmap, float scale) {
        Matrix matrix = new Matrix();
        matrix.setRotate(scale);
        bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        return bitmap;
    }

    /**
     * 根据路径和名字保存图片
     *
     * @param path
     *            path
     * @param imgName
     *            imgName
     * @param bitmap
     *            bitmap
     * @return createPath
     */
    public static String saveBitmap(String path, String imgName, Bitmap bitmap) {
        String savePath;
        if (path == null) { // if path is null
            File fileSDCardDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
            String imgPath = fileSDCardDir.getAbsolutePath() + "/s/waterCamera/";
            File fileDir = new File(imgPath);
            if (!fileDir.exists()) {
                fileDir.mkdirs();
            }
            String photoName = imgName + ".JPG";
            imgPath = imgPath + photoName;
            File fileIphoto = new File(imgPath);
            if (!fileIphoto.exists()) {
                try {
                    fileIphoto.createNewFile();
                } catch (IOException e) {

                }
            }
            savePath = fileIphoto.getPath();
            storeImage(bitmap, savePath);
            return savePath;
        } else { // if path isn't null, override the photo
            File oldFile = new File(path);
            if (oldFile.exists()) {
                oldFile.delete();
            }
            File newFile = new File(path);
            if (!newFile.exists()) {
                try {
                    newFile.createNewFile();
                } catch (IOException e) {

                }
            }
            // saveBitmap(bitmap, newFile);
            storeImage(bitmap, path);
            savePath = newFile.getPath();
            return savePath;
        }
    }

    public static void deleteImageFromSDCard(String path) {
        File oldFile = new File(path);
        if (oldFile.exists()) {
            oldFile.delete();
        }
    }

    /*
     * 设置相机Preview Size 和 Picture Size，找到设备所支持的最匹配的相机预览和图片大小
     */
//    public static void setCameraSize(Camera.Parameters parameters, int width, int height) {
//        Map<String, List<Camera.Size>> allSizes = new HashMap<String, List<Camera.Size>>();
//        String typePreview = "typePreview";
//        String typePicture = "typePicture";
//        allSizes.put(typePreview, parameters.getSupportedPreviewSizes());
//        allSizes.put(typePicture, parameters.getSupportedPictureSizes());
//        Iterator iterator = allSizes.entrySet().iterator();
//        while (iterator.hasNext()) {
//            Map.Entry<String, List<Camera.Size>> entry = (Map.Entry<String, List<Camera.Size>>) iterator.next();
//            List<Camera.Size> sizes = entry.getValue();
//            if (sizes == null || sizes.isEmpty())
//                continue;
//            ArrayList<WrapCameraSize> wrapCameraSizes = new ArrayList<WrapCameraSize>(sizes.size());
//            for (Camera.Size size : sizes) {
//                WrapCameraSize wrapCameraSize = new WrapCameraSize();
//                wrapCameraSize.setWidth(size.width);
//                wrapCameraSize.setHeight(size.height);
//                wrapCameraSize.setD(Math.abs((size.width - width)) + Math.abs((size.height - height)));
//                if (size.width == width && size.height == height) {
//                    if (typePreview.equals(entry.getKey())) {
//                        parameters.setPreviewSize(size.width, size.height);
//                    } else if (typePicture.equals(entry.getKey())) {
//                        parameters.setPictureSize(size.width, size.height);
//                    }
//                    LogUtils.d( "best size: width=" + size.width + ";height=" + size.height);
//                    break;
//                }
//                wrapCameraSizes.add(wrapCameraSize);
//            }
//            LogUtils.d( "wrapCameraSizes.size()=" + wrapCameraSizes.size());
//            Camera.Size resultSize = null;
//            if (typePreview.equals(entry.getKey())) {
//                resultSize = parameters.getPreviewSize();
//            } else if (typePicture.equals(entry.getKey())) {
//                resultSize = parameters.getPictureSize();
//            }
//            if (resultSize != null) {
//                if (resultSize.width != width && resultSize.height != height) {
//                    // 找到相机Preview Size 和 Picture Size中最适合的大小
//                    WrapCameraSize minCameraSize = Collections.min(wrapCameraSizes);
//                    while (!(minCameraSize.getWidth() >= width && minCameraSize.getHeight() >= height)) {
//                        wrapCameraSizes.remove(minCameraSize);
//                        minCameraSize = Collections.min(wrapCameraSizes);
//                    }
//                    LogUtils.d( "best min size: width=" + minCameraSize.getWidth() + ";height="
//                            + minCameraSize.getHeight());
//                    if (typePreview.equals(entry.getKey())) {
//                        parameters.setPreviewSize(minCameraSize.getWidth(), minCameraSize.getHeight());
//                    } else if (typePicture.equals(entry.getKey())) {
//                        parameters.setPictureSize(minCameraSize.getWidth(), minCameraSize.getHeight());
//                    }
//                }
//            }
//            iterator.remove();
//        }
//    }

    /**
     * 把两个位图覆盖合成为一个位图，以底层位图的长宽为基准
     *
     * @param backBitmap
     *            在底部的位图
     * @param frontBitmap
     *            盖在上面的位图
     * @return
     */
    public static Bitmap mergeBitmap(Bitmap backBitmap, Bitmap frontBitmap) {

        if (backBitmap == null || backBitmap.isRecycled() || frontBitmap == null || frontBitmap.isRecycled()) {
//            LogUtils.d( "backBitmap=" + backBitmap + ";frontBitmap=" + frontBitmap);
            return null;
        }
        Bitmap bitmap = backBitmap.copy(Config.ARGB_8888, true);
        Canvas canvas = new Canvas(bitmap);
        Rect baseRect = new Rect(0, 0, backBitmap.getWidth(), backBitmap.getHeight());
        Rect frontRect = new Rect(0, 0, frontBitmap.getWidth(), frontBitmap.getHeight());
        canvas.drawBitmap(frontBitmap, frontRect, baseRect, null);
        return bitmap;
    }

    public static Bitmap yuv2Bitmap(byte[] data, int width, int height) {
        YuvImage image = new YuvImage(data, 17, width, height, null);
        ByteArrayOutputStream os = new ByteArrayOutputStream(data.length);
        if (!image.compressToJpeg(new Rect(0, 0, width, height), 100, os)) {
            return null;
        } else {
            byte[] tmp = os.toByteArray();
            Bitmap bitmap = BitmapFactory.decodeByteArray(tmp, 0, tmp.length);
            return bitmap;
        }
    }

    // 把布局变成Bitmap
    public static Bitmap getViewBitmap(View addViewContent) {

        addViewContent.setDrawingCacheEnabled(true);

        addViewContent.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        addViewContent.layout(0, 0, addViewContent.getMeasuredWidth(), addViewContent.getMeasuredHeight());

        addViewContent.buildDrawingCache();
        Bitmap cacheBitmap = addViewContent.getDrawingCache();
        Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);

        return bitmap;
    }


    /**
     * 设置水印图片在左上角
     *
     * @param src
     * @param watermark
     * @param paddingLeft
     * @param paddingTop
     * @return
     */
//    public static Bitmap createWaterMaskLeftTop( Context context,Bitmap src, Bitmap watermark,
//                                                 int paddingLeft, int paddingTop) {
//        return createWaterMaskBitmap( src,  watermark,
//                Utils.dip2px(context, paddingLeft),
//                Utils.dip2px(context, paddingTop));
//    }

    private static Bitmap createWaterMaskBitmap(Bitmap src, Bitmap watermark,
                                                int paddingLeft, int paddingTop) {
        if (src == null) {
            return null;
        }
        int width = src.getWidth();
        int height = src.getHeight();
        //创建一个bitmap
        Bitmap newBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图
        //将该图片作为画布
        Canvas canvas = new Canvas(newBitmap);
        //在画布 0，0坐标上开始绘制原始图片
        canvas.drawBitmap(src, 0, 0, null);
        //在画布上绘制水印图片
        canvas.drawBitmap(watermark, paddingLeft, paddingTop, null);
        // 保存
        /*  canvas.save(Canvas.ALL_SAVE_FLAG);*/
        canvas.save();
        // canvas.save();
        // 存储
        canvas.restore();
        return newBitmap;
    }

    /**
     * 设置水印图片在右下角
     *
     * @param context
     * @param src
     * @param watermark
     * @param paddingRight
     * @param paddingBottom
     * @return
     */
//    public static Bitmap createWaterMaskRightBottom(
//            Context context, Bitmap src, Bitmap watermark,
//            int paddingRight, int paddingBottom) {
//        return createWaterMaskBitmap(src, watermark,
//                src.getWidth() - watermark.getWidth() - Utils.dip2px(context, paddingRight),
//                src.getHeight() - watermark.getHeight() - Utils.dip2px(context, paddingBottom));
//    }
}
